package nl.sportan.samenloop.communication.flickr;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import nl.sportan.samenloop.communication.PhotoTarget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.gmail.yuyang226.flickr.Flickr;
import com.gmail.yuyang226.flickr.FlickrException;
import com.gmail.yuyang226.flickr.photos.Photo;
import com.gmail.yuyang226.flickr.photos.PhotosInterface;
import com.gmail.yuyang226.flickr.photos.Size;

/**
 * Reads Bitmap data from Cache if available, retrieve them to the cache from
 * Flickr otherwise
 * 
 * @author Bram Wiekens
 * 
 */
public class PhotoDataRetriever implements Runnable {

	private PhotoTarget target;
	private Photo photo;
	private int size;
	private Context ctx;
	private boolean cache;

	public PhotoDataRetriever(Context ctx, Photo photo, int size,
			PhotoTarget target, boolean cache) {
		this.ctx = ctx;
		this.size = size;
		this.photo = photo;
		this.target = target;
		this.cache = cache;
	}
	
	private String getFileName(Photo photo, int size) {
		String url = "";
		if (size == Size.LARGE) {
			url = photo.getLargeUrl();
		}
		if (size == Size.MEDIUM) {
			url = photo.getMediumUrl();
		}
		if (size == Size.SMALL) {
			url = photo.getSmallUrl();
		}
		if (size == Size.SQUARE) {
			url = photo.getSmallSquareUrl();
		}

		int offset = url.lastIndexOf('/');
		String filename = url.substring(offset + 1);

		return filename;
	}

	private Bitmap getBitmap(Photo photo, int size, Boolean cache)
			throws FileNotFoundException {
		if (!cache) {
			return getFromFlickr(photo, size);
		} else {
			File file = getFileFromCache(photo, size);

			if (file != null) {

				InputStream is = new BufferedInputStream(new FileInputStream(
						file));
				Bitmap bp = BitmapFactory.decodeStream(is);

				return bp;

			} else {
				throw new FileNotFoundException("File is null");
			}
		}
	}

	private Bitmap getFromFlickr(Photo photo, int size) {
		Bitmap bp = null;
		
		try {
			Flickr f = new Flickr(FlickrConstants.APIKEY);
			PhotosInterface pi = f.getPhotosInterface();

			BufferedInputStream is = new BufferedInputStream(pi.getImageAsStream(
					photo, size));

			bp = BitmapFactory.decodeStream(is);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FlickrException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return bp;
	}

	private File writeToCache(Photo photo, int size) {
		Flickr f = new Flickr(FlickrConstants.APIKEY);

		PhotosInterface pi = f.getPhotosInterface();

		try {
			File cachedir = ctx.getCacheDir();
			if (!cachedir.exists()) {
				cachedir.mkdirs();
			}

			BufferedInputStream is = new BufferedInputStream(
					pi.getImageAsStream(photo, size));

			String filename = getFileName(photo, size);

			File cacheFile = new File(cachedir, filename);

			OutputStream fos = new BufferedOutputStream(new FileOutputStream(
					cacheFile));

			byte[] buffer = new byte[1024];
			int len = 0;

			while ((len = is.read(buffer)) > 0) {
				fos.write(buffer, 0, len);

			}

			is.close();
			fos.close();

			return cacheFile;

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FlickrException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	private File getFileFromCache(Photo photo, int size) {
		File cachedir = ctx.getCacheDir();
		if (!cachedir.exists()) {
			cachedir.mkdirs();
		}

		String filename = getFileName(photo, size);

		File[] files = cachedir.listFiles();

		for (File file : files) {
			String name = file.getName();
			if (name.equals(filename)) {
				return file;
			}
		}

		return writeToCache(photo, size);
	}

	public void run() {

		try {
			Bitmap bp = getBitmap(photo, size, cache);
			target.setPhoto(bp);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}